ItemController – Ember.js入門(13)
渡辺です。新年早々ですが、ガツガツいきましょう。
今回は、ItemControllerを紹介します。ItemControllerは、リスト表示などを行う時、モデルの情報を加工した値や、Viewに依存した値を出力するためによく使われます。しかし、ItemControllerは、Ember.jsでも利用頻度も高く非常に便利な機能なのですが、公式ドキュメントではチュートリアルにさらりと書いてあるだけでAPIドキュメントにしか記述されていないため、見つけにくい機能かもしれません。
ItemControllerとは?
前回のObjectControllerとArrayController – Ember.js入門(12)では、ArrayControllerを解説しました。ArrayControllerはModelが複数の場合に利用するControllerで、View(テンプレート)ではeachヘルパーによる反復表示を行うことができます。
App.ApplicationRoute = Ember.Route.extend({ model: function() { return [ {name: 'サッポロクラシック', unitPrice: 250, quantity: 5}, {name: 'ニッカ余市', unitPrice: 2200, quantity: 1}, {name: '小樽ワイン', unitPrice: 950, quantity: 2} ]; } }); App.ApplicationController = Ember.ArrayController.extend({ });
<script type="text/x-handlebars"> <h2>ご注文</h2> <ul> {{#each}} <li>{{name}}</li> {{/each}} </ul> </script>
この時、eachの内部ではモデルのプロパティにアクセスできますが、Computed Propertyを利用するにはModelに定義しなければなりません。Modelに相応しいComputed Propertyであれば問題ありませんが、Viewに依存するようなCSSのクラス名などをModelに定義するのはよろしくありません。
このような場合に、eachの内部で局地的に適用できるControllerがItemControllerです。
ItemControllerの定義
ItemControllerは通常のControllerと同様に、Ember.ObjectControllerのサブクラスとして定義します。ItemControllerには利用される時にeachで反復処理される個々のModelがコンテキストオブジェクトとして設定されることを前提にComputed Propertyなどを定義します。次のコードでは、ModelのunitPriceプロパティとquantityプロパティを掛けた値をsubtotalとして定義しています。
App.OrderController = Ember.ObjectController.extend({ subtotal: function() { return this.get('unitPrice') * this.get('quantity'); }.property('unitPrice', 'quantity') });
ItemControllerの指定
ItemControllerを利用する方法は2つあります。
eachヘルパーのitemController属性に指定する
ひとつ目の方法はeachヘルパーのitemController属性に指定する方法です。
<ul> {{#each itemController="order"}} <li>{{name}} - ¥{{subtotal}}(¥{{unitPrice}}×{{quantity}})</li> {{/each}} </ul>
eachで反復されるのはControllerのコンテキストオブジェクトとなる配列です。それぞれの要素がitemControllerで指定されたControllerのコンテキストオブジェクトとなります。したがって、Modelの各プロパティにアクセス可能で、かつItemControllerに追加されたComputed Propertyなどにもアクセスできます。
なお、itemController属性に指定する場合、クラス名(App.OrderController)ではなくlookup名(小文字始まりでControllerをつけない形式)で指定します。
ArrayControllerのitemControllerプロパティに指定する
ItemControllerはArrayControllerのitemControllerプロパティに指定することもできます。
App.ApplicationController = Ember.ArrayController.extend({ itemController: "order" });
効果についてはeachヘルパーの場合と変わりません。
この場合、eachヘルパーのitemController属性を指定しなくともOrderControllerが利用されます。もし、両方が指定されていたならばeachヘルパー側が優先されます。
まとめ
ItemControllerは反復処理対象のModelに対し、個々の独立したControllerを提供します。したがって、ArrayControllerでModel毎のComputed Propertyを定義する時に便利に利用することができます。また、ItemControllerは通常のControllerと同じだけの機能を持ちますので、Model毎の状態やactionを定義することも容易です。ItemControllerを活用し、粒度が揃ったEmber.jsのコードを構築してください。